import { AirData, transitionAltitude } from '@/atmosphere'
import { getBADAModel } from './core'
import {
  type FlightEnvelopeItem,
  airDataByFL,
  cVMin,
  flightLevels,
  getKClimbStallCAS
} from './flight-envelope'
import type { AirlineProcedure, BADAAircraftTypeModel, OperationPerformance } from './types'
import { ft2m, kt2Mps } from '@/widgets'

export interface ProcedureProfile {
  procedure: AirlineProcedure
  line: FlightEnvelopeItem[]
}

export function calcClimbAirlineProcedureById(id: string): ProcedureProfile {
  const model = getBADAModel(id)!
  return calcClimbAirlineProcedure(model)
}

export function calcClimbAirlineProcedureXById(id: string, f: number): FlightEnvelopeItem[] {
  const model = getBADAModel(id)!
  return calcClimbAirlineProcedureX(model, f)
}

function calcClimbAirlineProcedureX(model: BADAAircraftTypeModel, f: number): FlightEnvelopeItem[] {
  const procedure = model.procedure
  const maxFt = model.performance.hMO
  let idx = 0
  const kStallTo = model.performance.vStallTO
  const stallTo = kt2Mps(kStallTo)
  const vMin = cVMin * stallTo
  const vMax = kt2Mps(model.performance.vMO)
  const mMax = model.performance.machMO
  const line: FlightEnvelopeItem[] = []
  for (const fl of flightLevels) {
    const altFt = fl * 100
    if (altFt > maxFt) {
      break
    }
    const ad = airDataByFL[idx]
    idx++
    const item = calcClimbAirlineProcedureItem(
      f,
      fl,
      procedure,
      model.performance,
      ad,
      vMin,
      vMax,
      mMax
    )
    line.push(item)
  }
  return line
}

function calcClimbAirlineProcedureItem(
  f: number,
  fl: number,
  p: AirlineProcedure,
  op: OperationPerformance,
  ad: AirData,
  vMin: number,
  vMax: number,
  mMax: number
): FlightEnvelopeItem {
  const altFt = fl * 100
  const alt = ft2m(altFt)
  let minSpd = getKClimbStallCAS(op, fl)
  minSpd = kt2Mps(minSpd) * cVMin
  const vCl1 = kt2Mps(Math.min(p.vCl1 * f, 250))
  // const minSpd = kt2Mps(getKClimbStallCAS(op, fl)) * cVMin
  if (fl < 100) {
    let cas = vMin
    if (fl < 15) {
      cas = vMin + kt2Mps(kCl1)
    } else if (fl < 30) {
      cas = vMin + kt2Mps(kCl2)
    } else if (fl < 40) {
      cas = vMin + kt2Mps(kCl3)
    } else if (fl < 50) {
      cas = vMin + kt2Mps(kCl4)
    } else if (fl < 60) {
      cas = vMin + kt2Mps(kCl5)
    } else {
      cas = vCl1
      // cas = kt2Mps(Math.min(p.vCl1, 250))
    }
    cas = cas * f
    cas = Math.max(cas, minSpd)
    cas = Math.min(cas, vCl1)
    cas = Math.min(cas, vMax)
    let tas = ad.CAS2TAS(cas)
    let mach = ad.TAS2Mach(tas)
    if (mach > mMax) {
      mach = mMax
      tas = ad.mach2TAS(mach)
      cas = ad.TAS2CAS(tas)
    }
    return { alt, cas, tas, mach }
  } else {
    const vCl2 = kt2Mps(p.vCl2)
    const transAlt = transitionAltitude(vCl2, p.mCl)
    if (alt < transAlt) {
      let cas = vCl2
      cas = cas * f
      cas = Math.max(cas, minSpd)
      cas = Math.min(cas, vMax)
      let tas = ad.CAS2TAS(cas)
      let mach = ad.TAS2Mach(tas)
      if (mach > mMax) {
        mach = mMax
        tas = ad.mach2TAS(mach)
        cas = ad.TAS2CAS(tas)
      }
      return { alt, cas, tas, mach }
    }
    let mach = p.mCl
    let tas = ad.mach2TAS(mach)
    let cas = ad.TAS2CAS(tas)
    cas *= f
    if (cas < minSpd) {
      cas = minSpd
    } else if (cas > vMax) {
      cas = vMax
    }
    tas = ad.CAS2TAS(cas)
    mach = ad.TAS2Mach(tas)
    if (mach > mMax) {
      mach = mMax
      tas = ad.mach2TAS(mach)
      cas = ad.TAS2CAS(tas)
    }
    return { alt, cas, tas, mach }
  }
}

const kCl1 = 5
const kCl2 = 10
const kCl3 = 30
const kCl4 = 60
const kCl5 = 80

function calcClimbAirlineProcedure(model: BADAAircraftTypeModel): ProcedureProfile {
  const procedure = model.procedure
  const line = calcClimbAirlineProcedureX(model, 1.0)
  return { procedure, line }
}
